﻿using System;
using System.Diagnostics;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using HslCommunication.Core;
using HslCommunication.Core.IMessage;
using HslCommunication.Core.Net;
using HslCommunication.Reflection;

namespace HslCommunication.Profinet.AllenBradley
{
	/// <summary>
	/// AllenBradley品牌的PLC，针对SLC系列的通信的实现，测试PLC为1747。<br />
	/// AllenBradley brand PLC, for the realization of SLC series communication, the test PLC is 1747.
	/// </summary>
	/// <remarks>
	/// 地址格式如下：
	/// <list type="table">
	///   <listheader>
	///     <term>地址代号</term>
	///     <term>字操作</term>
	///     <term>位操作</term>
	///     <term>备注</term>
	///   </listheader>
	///   <item>
	///     <term>A</term>
	///     <term>A9:0</term>
	///     <term>A9:0/1 或 A9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>B</term>
	///     <term>B9:0</term>
	///     <term>B9:0/1 或 B9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>N</term>
	///     <term>N9:0</term>
	///     <term>N9:0/1 或 N9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>F</term>
	///     <term>F9:0</term>
	///     <term>F9:0/1 或 F9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>S</term>
	///     <term>S:0</term>
	///     <term>S:0/1 或 S:0.1</term>
	///     <term>S:0 等同于 S2:0</term>
	///   </item>
	///   <item>
	///     <term>C</term>
	///     <term>C9:0</term>
	///     <term>C9:0/1 或 C9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>I</term>
	///     <term>I9:0</term>
	///     <term>I9:0/1 或 I9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>O</term>
	///     <term>O9:0</term>
	///     <term>O9:0/1 或 O9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>R</term>
	///     <term>R9:0</term>
	///     <term>R9:0/1 或 R9:0.1</term>
	///     <term></term>
	///   </item>
	///   <item>
	///     <term>T</term>
	///     <term>T9:0</term>
	///     <term>T9:0/1 或 T9:0.1</term>
	///     <term></term>
	///   </item>
	/// </list>
	/// 感谢 seedee 的测试支持。
	/// </remarks>
	// Token: 0x020000BB RID: 187
	public class AllenBradleySLCNet : NetworkDeviceBase
	{
		/// <summary>
		/// Instantiate a communication object for a Allenbradley PLC protocol
		/// </summary>
		// Token: 0x06000DEC RID: 3564 RVA: 0x00052929 File Offset: 0x00050B29
		public AllenBradleySLCNet()
		{
			base.WordLength = 2;
			base.ByteTransform = new RegularByteTransform();
		}

		/// <summary>
		/// Instantiate a communication object for a Allenbradley PLC protocol
		/// </summary>
		/// <param name="ipAddress">PLC IpAddress</param>
		/// <param name="port">PLC Port</param>
		// Token: 0x06000DED RID: 3565 RVA: 0x00052947 File Offset: 0x00050B47
		public AllenBradleySLCNet(string ipAddress, int port = 44818)
		{
			base.WordLength = 2;
			this.IpAddress = ipAddress;
			this.Port = port;
			base.ByteTransform = new RegularByteTransform();
		}

		/// <inheritdoc />
		// Token: 0x06000DEE RID: 3566 RVA: 0x00052975 File Offset: 0x00050B75
		protected override INetMessage GetNewNetMessage()
		{
			return new AllenBradleySLCMessage();
		}

		/// <summary>
		/// The current session handle, which is determined by the PLC when communicating with the PLC handshake
		/// </summary>
		// Token: 0x17000206 RID: 518
		// (get) Token: 0x06000DEF RID: 3567 RVA: 0x0005297C File Offset: 0x00050B7C
		// (set) Token: 0x06000DF0 RID: 3568 RVA: 0x00052984 File Offset: 0x00050B84
		public uint SessionHandle { get; protected set; }

		/// <inheritdoc />
		// Token: 0x06000DF1 RID: 3569 RVA: 0x00052990 File Offset: 0x00050B90
		protected override OperateResult InitializationOnConnect(Socket socket)
		{
			OperateResult<byte[]> operateResult = this.ReadFromCoreServer(socket, "01 01 00 00 00 00 00 00 00 00 00 00 00 04 00 05 00 00 00 00 00 00 00 00 00 00 00 00".ToHexBytes(), true, true);
			bool flag = !operateResult.IsSuccess;
			OperateResult result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				this.SessionHandle = base.ByteTransform.TransUInt32(operateResult.Content, 4);
				result = OperateResult.CreateSuccessResult();
			}
			return result;
		}

		/// <inheritdoc />
		// Token: 0x06000DF2 RID: 3570 RVA: 0x000529E8 File Offset: 0x00050BE8
		[DebuggerStepThrough]
		protected override Task<OperateResult> InitializationOnConnectAsync(Socket socket)
		{
			AllenBradleySLCNet.<InitializationOnConnectAsync>d__8 <InitializationOnConnectAsync>d__ = new AllenBradleySLCNet.<InitializationOnConnectAsync>d__8();
			<InitializationOnConnectAsync>d__.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
			<InitializationOnConnectAsync>d__.<>4__this = this;
			<InitializationOnConnectAsync>d__.socket = socket;
			<InitializationOnConnectAsync>d__.<>1__state = -1;
			<InitializationOnConnectAsync>d__.<>t__builder.Start<AllenBradleySLCNet.<InitializationOnConnectAsync>d__8>(ref <InitializationOnConnectAsync>d__);
			return <InitializationOnConnectAsync>d__.<>t__builder.Task;
		}

		/// <summary>
		/// Read data information, data length for read array length information
		/// </summary>
		/// <param name="address">Address format of the node</param>
		/// <param name="length">In the case of arrays, the length of the array </param>
		/// <returns>Result data with result object </returns>
		// Token: 0x06000DF3 RID: 3571 RVA: 0x00052A34 File Offset: 0x00050C34
		[HslMqttApi("ReadByteArray", "")]
		public override OperateResult<byte[]> Read(string address, ushort length)
		{
			OperateResult<byte[]> operateResult = AllenBradleySLCNet.BuildReadCommand(address, length);
			bool flag = !operateResult.IsSuccess;
			OperateResult<byte[]> result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				OperateResult<byte[]> operateResult2 = base.ReadFromCoreServer(this.PackCommand(operateResult.Content));
				bool flag2 = !operateResult2.IsSuccess;
				if (flag2)
				{
					result = operateResult2;
				}
				else
				{
					OperateResult<byte[]> operateResult3 = AllenBradleySLCNet.ExtraActualContent(operateResult2.Content);
					bool flag3 = !operateResult3.IsSuccess;
					if (flag3)
					{
						result = operateResult3;
					}
					else
					{
						result = OperateResult.CreateSuccessResult<byte[]>(operateResult3.Content);
					}
				}
			}
			return result;
		}

		/// <inheritdoc />
		// Token: 0x06000DF4 RID: 3572 RVA: 0x00052AB4 File Offset: 0x00050CB4
		[HslMqttApi("WriteByteArray", "")]
		public override OperateResult Write(string address, byte[] value)
		{
			OperateResult<byte[]> operateResult = AllenBradleySLCNet.BuildWriteCommand(address, value);
			bool flag = !operateResult.IsSuccess;
			OperateResult result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				OperateResult<byte[]> operateResult2 = base.ReadFromCoreServer(this.PackCommand(operateResult.Content));
				bool flag2 = !operateResult2.IsSuccess;
				if (flag2)
				{
					result = operateResult2;
				}
				else
				{
					OperateResult<byte[]> operateResult3 = AllenBradleySLCNet.ExtraActualContent(operateResult2.Content);
					bool flag3 = !operateResult3.IsSuccess;
					if (flag3)
					{
						result = operateResult3;
					}
					else
					{
						result = OperateResult.CreateSuccessResult<byte[]>(operateResult3.Content);
					}
				}
			}
			return result;
		}

		/// <inheritdoc />
		// Token: 0x06000DF5 RID: 3573 RVA: 0x00052B34 File Offset: 0x00050D34
		[HslMqttApi("ReadBool", "")]
		public override OperateResult<bool> ReadBool(string address)
		{
			int num;
			address = AllenBradleySLCNet.AnalysisBitIndex(address, out num);
			OperateResult<byte[]> operateResult = this.Read(address, 1);
			bool flag = !operateResult.IsSuccess;
			OperateResult<bool> result;
			if (flag)
			{
				result = OperateResult.CreateFailedResult<bool>(operateResult);
			}
			else
			{
				result = OperateResult.CreateSuccessResult<bool>(operateResult.Content.ToBoolArray()[num]);
			}
			return result;
		}

		/// <inheritdoc />
		// Token: 0x06000DF6 RID: 3574 RVA: 0x00052B84 File Offset: 0x00050D84
		[HslMqttApi("WriteBool", "")]
		public override OperateResult Write(string address, bool value)
		{
			OperateResult<byte[]> operateResult = AllenBradleySLCNet.BuildWriteCommand(address, value);
			bool flag = !operateResult.IsSuccess;
			OperateResult result;
			if (flag)
			{
				result = operateResult;
			}
			else
			{
				OperateResult<byte[]> operateResult2 = base.ReadFromCoreServer(this.PackCommand(operateResult.Content));
				bool flag2 = !operateResult2.IsSuccess;
				if (flag2)
				{
					result = operateResult2;
				}
				else
				{
					OperateResult<byte[]> operateResult3 = AllenBradleySLCNet.ExtraActualContent(operateResult2.Content);
					bool flag3 = !operateResult3.IsSuccess;
					if (flag3)
					{
						result = operateResult3;
					}
					else
					{
						result = OperateResult.CreateSuccessResult<byte[]>(operateResult3.Content);
					}
				}
			}
			return result;
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.AllenBradley.AllenBradleySLCNet.Read(System.String,System.UInt16)" />
		// Token: 0x06000DF7 RID: 3575 RVA: 0x00052C04 File Offset: 0x00050E04
		[DebuggerStepThrough]
		public override Task<OperateResult<byte[]>> ReadAsync(string address, ushort length)
		{
			AllenBradleySLCNet.<ReadAsync>d__13 <ReadAsync>d__ = new AllenBradleySLCNet.<ReadAsync>d__13();
			<ReadAsync>d__.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
			<ReadAsync>d__.<>4__this = this;
			<ReadAsync>d__.address = address;
			<ReadAsync>d__.length = length;
			<ReadAsync>d__.<>1__state = -1;
			<ReadAsync>d__.<>t__builder.Start<AllenBradleySLCNet.<ReadAsync>d__13>(ref <ReadAsync>d__);
			return <ReadAsync>d__.<>t__builder.Task;
		}

		/// <inheritdoc />
		// Token: 0x06000DF8 RID: 3576 RVA: 0x00052C58 File Offset: 0x00050E58
		[DebuggerStepThrough]
		public override Task<OperateResult> WriteAsync(string address, byte[] value)
		{
			AllenBradleySLCNet.<WriteAsync>d__14 <WriteAsync>d__ = new AllenBradleySLCNet.<WriteAsync>d__14();
			<WriteAsync>d__.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
			<WriteAsync>d__.<>4__this = this;
			<WriteAsync>d__.address = address;
			<WriteAsync>d__.value = value;
			<WriteAsync>d__.<>1__state = -1;
			<WriteAsync>d__.<>t__builder.Start<AllenBradleySLCNet.<WriteAsync>d__14>(ref <WriteAsync>d__);
			return <WriteAsync>d__.<>t__builder.Task;
		}

		/// <inheritdoc />
		// Token: 0x06000DF9 RID: 3577 RVA: 0x00052CAC File Offset: 0x00050EAC
		[DebuggerStepThrough]
		public override Task<OperateResult<bool>> ReadBoolAsync(string address)
		{
			AllenBradleySLCNet.<ReadBoolAsync>d__15 <ReadBoolAsync>d__ = new AllenBradleySLCNet.<ReadBoolAsync>d__15();
			<ReadBoolAsync>d__.<>t__builder = AsyncTaskMethodBuilder<OperateResult<bool>>.Create();
			<ReadBoolAsync>d__.<>4__this = this;
			<ReadBoolAsync>d__.address = address;
			<ReadBoolAsync>d__.<>1__state = -1;
			<ReadBoolAsync>d__.<>t__builder.Start<AllenBradleySLCNet.<ReadBoolAsync>d__15>(ref <ReadBoolAsync>d__);
			return <ReadBoolAsync>d__.<>t__builder.Task;
		}

		/// <inheritdoc />
		// Token: 0x06000DFA RID: 3578 RVA: 0x00052CF8 File Offset: 0x00050EF8
		[DebuggerStepThrough]
		public override Task<OperateResult> WriteAsync(string address, bool value)
		{
			AllenBradleySLCNet.<WriteAsync>d__16 <WriteAsync>d__ = new AllenBradleySLCNet.<WriteAsync>d__16();
			<WriteAsync>d__.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
			<WriteAsync>d__.<>4__this = this;
			<WriteAsync>d__.address = address;
			<WriteAsync>d__.value = value;
			<WriteAsync>d__.<>1__state = -1;
			<WriteAsync>d__.<>t__builder.Start<AllenBradleySLCNet.<WriteAsync>d__16>(ref <WriteAsync>d__);
			return <WriteAsync>d__.<>t__builder.Task;
		}

		// Token: 0x06000DFB RID: 3579 RVA: 0x00052D4C File Offset: 0x00050F4C
		private byte[] PackCommand(byte[] coreCmd)
		{
			byte[] array = new byte[28 + coreCmd.Length];
			array[0] = 1;
			array[1] = 7;
			array[2] = (byte)(coreCmd.Length / 256);
			array[3] = (byte)(coreCmd.Length % 256);
			BitConverter.GetBytes(this.SessionHandle).CopyTo(array, 4);
			coreCmd.CopyTo(array, 28);
			return array;
		}

		/// <summary>
		/// 分析地址数据信息里的位索引的信息
		/// </summary>
		/// <param name="address">数据地址</param>
		/// <param name="bitIndex">位索引</param>
		/// <returns>地址信息</returns>
		// Token: 0x06000DFC RID: 3580 RVA: 0x00052DAC File Offset: 0x00050FAC
		public static string AnalysisBitIndex(string address, out int bitIndex)
		{
			bitIndex = 0;
			int num = address.IndexOf('/');
			bool flag = num < 0;
			if (flag)
			{
				num = address.IndexOf('.');
			}
			bool flag2 = num > 0;
			if (flag2)
			{
				bitIndex = int.Parse(address.Substring(num + 1));
				address = address.Substring(0, num);
			}
			return address;
		}

		/// <summary>
		/// 分析当前的地址信息，返回类型代号，区块号，其实地址<br />
		/// Analyze the current address information, return the type code, block number, and actual address
		/// </summary>
		/// <param name="address">地址信息</param>
		/// <returns>结果内容对象</returns>
		// Token: 0x06000DFD RID: 3581 RVA: 0x00052E00 File Offset: 0x00051000
		public static OperateResult<byte, byte, ushort> AnalysisAddress(string address)
		{
			bool flag = !address.Contains(":");
			OperateResult<byte, byte, ushort> result;
			if (flag)
			{
				result = new OperateResult<byte, byte, ushort>("Address can't find ':', example : A9:0");
			}
			else
			{
				string[] array = address.Split(new char[]
				{
					':'
				});
				try
				{
					OperateResult<byte, byte, ushort> operateResult = new OperateResult<byte, byte, ushort>();
					char c = array[0][0];
					char c2 = c;
					switch (c2)
					{
					case 'A':
						operateResult.Content1 = 142;
						goto IL_140;
					case 'B':
						operateResult.Content1 = 133;
						goto IL_140;
					case 'C':
						operateResult.Content1 = 135;
						goto IL_140;
					case 'D':
					case 'E':
					case 'G':
					case 'H':
						break;
					case 'F':
						operateResult.Content1 = 138;
						goto IL_140;
					case 'I':
						operateResult.Content1 = 131;
						goto IL_140;
					default:
						switch (c2)
						{
						case 'N':
							operateResult.Content1 = 137;
							goto IL_140;
						case 'O':
							operateResult.Content1 = 130;
							goto IL_140;
						case 'R':
							operateResult.Content1 = 136;
							goto IL_140;
						case 'S':
							operateResult.Content1 = 132;
							goto IL_140;
						case 'T':
							operateResult.Content1 = 134;
							goto IL_140;
						}
						break;
					}
					throw new Exception("Address code wrong, must be A,B,N,F,S,C,I,O,R,T");
					IL_140:
					bool flag2 = operateResult.Content1 == 132;
					if (flag2)
					{
						operateResult.Content2 = 2;
					}
					else
					{
						operateResult.Content2 = byte.Parse(array[0].Substring(1));
					}
					operateResult.Content3 = ushort.Parse(array[1]);
					operateResult.IsSuccess = true;
					operateResult.Message = StringResources.Language.SuccessText;
					result = operateResult;
				}
				catch (Exception ex)
				{
					result = new OperateResult<byte, byte, ushort>("Wrong Address formate: " + ex.Message);
				}
			}
			return result;
		}

		/// <summary>
		/// 构建读取的指令信息
		/// </summary>
		/// <param name="address">地址信息，举例：A9:0</param>
		/// <param name="length">读取的长度信息</param>
		/// <returns>是否成功</returns>
		// Token: 0x06000DFE RID: 3582 RVA: 0x00052FEC File Offset: 0x000511EC
		public static OperateResult<byte[]> BuildReadCommand(string address, ushort length)
		{
			OperateResult<byte, byte, ushort> operateResult = AllenBradleySLCNet.AnalysisAddress(address);
			bool flag = !operateResult.IsSuccess;
			OperateResult<byte[]> result;
			if (flag)
			{
				result = OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			else
			{
				bool flag2 = length < 2;
				if (flag2)
				{
					length = 2;
				}
				bool flag3 = operateResult.Content1 == 142;
				if (flag3)
				{
					OperateResult<byte, byte, ushort> operateResult2 = operateResult;
					operateResult2.Content3 /= 2;
				}
				byte[] array = new byte[14];
				array[0] = 0;
				array[1] = 5;
				array[2] = 0;
				array[3] = 0;
				array[4] = 15;
				array[5] = 0;
				array[6] = 0;
				array[7] = 1;
				array[8] = 162;
				array[9] = (byte)length;
				array[10] = operateResult.Content2;
				array[11] = operateResult.Content1;
				BitConverter.GetBytes(operateResult.Content3).CopyTo(array, 12);
				result = OperateResult.CreateSuccessResult<byte[]>(array);
			}
			return result;
		}

		/// <summary>
		/// 构建写入的报文内容，变成实际的数据
		/// </summary>
		/// <param name="address">地址信息</param>
		/// <param name="value">数据值</param>
		/// <returns>是否成功的结果对象</returns>
		// Token: 0x06000DFF RID: 3583 RVA: 0x000530B8 File Offset: 0x000512B8
		public static OperateResult<byte[]> BuildWriteCommand(string address, byte[] value)
		{
			OperateResult<byte, byte, ushort> operateResult = AllenBradleySLCNet.AnalysisAddress(address);
			bool flag = !operateResult.IsSuccess;
			OperateResult<byte[]> result;
			if (flag)
			{
				result = OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			else
			{
				bool flag2 = operateResult.Content1 == 142;
				if (flag2)
				{
					OperateResult<byte, byte, ushort> operateResult2 = operateResult;
					operateResult2.Content3 /= 2;
				}
				byte[] array = new byte[18 + value.Length];
				array[0] = 0;
				array[1] = 5;
				array[2] = 0;
				array[3] = 0;
				array[4] = 15;
				array[5] = 0;
				array[6] = 0;
				array[7] = 1;
				array[8] = 171;
				array[9] = byte.MaxValue;
				array[10] = BitConverter.GetBytes(value.Length)[0];
				array[11] = BitConverter.GetBytes(value.Length)[1];
				array[12] = operateResult.Content2;
				array[13] = operateResult.Content1;
				BitConverter.GetBytes(operateResult.Content3).CopyTo(array, 14);
				array[16] = byte.MaxValue;
				array[17] = byte.MaxValue;
				value.CopyTo(array, 18);
				result = OperateResult.CreateSuccessResult<byte[]>(array);
			}
			return result;
		}

		/// <summary>
		/// 构建写入的报文内容，变成实际的数据
		/// </summary>
		/// <param name="address">地址信息</param>
		/// <param name="value">数据值</param>
		/// <returns>是否成功的结果对象</returns>
		// Token: 0x06000E00 RID: 3584 RVA: 0x000531B4 File Offset: 0x000513B4
		public static OperateResult<byte[]> BuildWriteCommand(string address, bool value)
		{
			int num;
			address = AllenBradleySLCNet.AnalysisBitIndex(address, out num);
			OperateResult<byte, byte, ushort> operateResult = AllenBradleySLCNet.AnalysisAddress(address);
			bool flag = !operateResult.IsSuccess;
			OperateResult<byte[]> result;
			if (flag)
			{
				result = OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			else
			{
				bool flag2 = operateResult.Content1 == 142;
				if (flag2)
				{
					OperateResult<byte, byte, ushort> operateResult2 = operateResult;
					operateResult2.Content3 /= 2;
				}
				int value2 = 1 << num;
				byte[] array = new byte[20];
				array[0] = 0;
				array[1] = 5;
				array[2] = 0;
				array[3] = 0;
				array[4] = 15;
				array[5] = 0;
				array[6] = 0;
				array[7] = 1;
				array[8] = 171;
				array[9] = byte.MaxValue;
				array[10] = 2;
				array[11] = 0;
				array[12] = operateResult.Content2;
				array[13] = operateResult.Content1;
				BitConverter.GetBytes(operateResult.Content3).CopyTo(array, 14);
				array[16] = BitConverter.GetBytes(value2)[0];
				array[17] = BitConverter.GetBytes(value2)[1];
				if (value)
				{
					array[18] = BitConverter.GetBytes(value2)[0];
					array[19] = BitConverter.GetBytes(value2)[1];
				}
				result = OperateResult.CreateSuccessResult<byte[]>(array);
			}
			return result;
		}

		/// <summary>
		/// 解析当前的实际报文内容，变成数据内容
		/// </summary>
		/// <param name="content">报文内容</param>
		/// <returns>是否成功</returns>
		// Token: 0x06000E01 RID: 3585 RVA: 0x000532CC File Offset: 0x000514CC
		public static OperateResult<byte[]> ExtraActualContent(byte[] content)
		{
			bool flag = content.Length < 36;
			OperateResult<byte[]> result;
			if (flag)
			{
				result = new OperateResult<byte[]>(StringResources.Language.ReceiveDataLengthTooShort + content.ToHexString(' '));
			}
			else
			{
				result = OperateResult.CreateSuccessResult<byte[]>(content.RemoveBegin(36));
			}
			return result;
		}
	}
}
